﻿using BaseicModuleExpression.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace BaseicModuleExpression.Module
{
    public class NewExpressionVistor : ExpressionVisitor
    {
        public ParameterExpression parameterExpression { get; set; }
        public NewExpressionVistor(ParameterExpression parameter)
        {
            this.parameterExpression = parameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return parameterExpression;
        }


    }

    public static class ExpressionVistorExtendP
    {
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression)
        {
            //return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
            ParameterExpression parameterExpression = Expression.Parameter(typeof(User), "w");
            NewExpressionVistor newExpressionVistor = new NewExpressionVistor(parameterExpression);
            Expression x = newExpressionVistor.Visit(expression1.Body);
            Expression p = newExpressionVistor.Visit(expression.Body);
            Expression news = Expression.And(x, p);
            return Expression.Lambda<Func<T, bool>>(news, new ParameterExpression[] { parameterExpression });
        }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression, Expression<Func<T, bool>> expression1)
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "w");
            NewExpressionVistor newExpressionVistor = new NewExpressionVistor(parameterExpression);
            Expression expression2 = newExpressionVistor.Visit(expression.Body);
            Expression expression3 = newExpressionVistor.Visit(expression1.Body);
            Expression expression4 = Expression.Or(expression2, expression3);
            return Expression.Lambda<Func<T, bool>>(expression4, new ParameterExpression[] { parameterExpression });
        }

        public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression)
        {
            ParameterExpression parameterExpression = expression.Parameters[0];
            Expression expression1 = expression.Body;
            UnaryExpression unaryExpression = Expression.Not(expression1);
            return Expression.Lambda<Func<T, bool>>(unaryExpression, new ParameterExpression[] { parameterExpression });
        }
    }
}
